﻿using SuperX.Common.APIManager;
using SuperX.Common.BasicService;
using SuperX.Common.Helper;
using SuperX.DataCenterService.MomAPI.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using SuperX.Common.Log;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace SuperX.DataCenterService.WebAPI
{
    public class MomController : ControllerBase
    {
        private static ILookup<string, MomRpcInfo> controllerMethods = null;
        private static readonly Dictionary<string, MomRpcInfo> Actions = new Dictionary<string, MomRpcInfo>(StringComparer.OrdinalIgnoreCase);
        private static readonly object Lock = new object();

        [HttpPost("root/rpc/service")]
        public Response RpcService([FromBody] Root obj)
        {
            var result = ExecutionAction("ScreenDesgin", obj.method, obj.@params.args);
            return result as Response;
        }

        [HttpPost("/root/attachment/upload")]
        public async Task<object> Upload()
        {
            if (!Request.HasFormContentType)
            {
                return StatusCode(415); // 返回不支持的媒体类型状态码
            }

            string root = Path.Combine(BasicServiceManager.GetProjService().Project.ProjectDir, "Runtime", "ScreenDesign");
            if (!Directory.Exists(root)) { Directory.CreateDirectory(root); }

            var formCollection = await Request.ReadFormAsync();
            var files = formCollection.Files;

            if (files.Count == 0)
            {
                return "No file uploaded";
            }

            foreach (var file in files)
            {
                var fileName = file.FileName;
                var filePath = Path.Combine(root, fileName);
                var fileID = Guid.NewGuid().ToString(); // 生成文件ID
                var size = file.Length;
                var type = Path.GetExtension(fileName).Trim('.');

                using (var stream = new FileStream(filePath, FileMode.Create))
                {
                    await file.CopyToAsync(stream);
                }

                // 处理文件信息，可以将信息存储到数据库或其他地方
                var fileInfo = new
                {
                    fileName,
                    fileID,
                    size,
                    type
                };

                // 在这里执行存储文件的操作，例如保存到服务器文件夹，或者将文件信息保存到数据库

                // 返回文件信息
                return fileInfo;
            }

            return "No file uploaded";
        }

        /// <summary>
        /// 接口调用
        /// </summary>
        /// <param name="ControllerName"></param>入口
        /// <param name="ActionName"></param>
        /// <param name="objects"></param>
        /// <returns></returns>
        ///
        public static object ExecutionAction(string ControllerName, string ActionName, object obj)
        {
            //初始化接口
            InitActions();
            //var Length = objects == null ? 0 : objects.Length;
            var key = $"{ControllerName.ToLower()}controller.{ActionName.ToLower()}.1";
            if (Actions.TryGetValue(key, out var ActionInvokeInfo))
            {
                var invokeResult = ExecutionInvoke(ActionInvokeInfo, obj);
                return invokeResult;
            }
            return new Response() { result = new Result { data = "找不到方法" } };
        }

        public static Dictionary<string, MomRpcInfo> InitActions()
        {
            if (Actions.Any()) return Actions;
            lock (Lock)
            {
                try
                {
                    var APICollection = BasicServiceManager.GetProjService().Project.Objects.Values.OfType<MomApi>();
                    var actionInfos = new List<MomRpcInfo>();
                    foreach (var item in APICollection)
                    {
                        try
                        {
                            actionInfos.AddRange(item.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
                             .Select(a => new MomRpcInfo()
                             {
                                 TypeObject = item,
                                 MethodInfo = a,
                                 MethodName = a.Name.ToLower(),
                                 Handler = DynamicEmitCalls.GetMethodInvoker(a),
                             }));
                        }
                        catch (Exception ex)
                        {
                            Logger.Error($"{item.Name}模组RPC初始化失败,失败信息{ex.Message}");
                        }
                    }
                    controllerMethods = actionInfos.ToLookup(a => a.MethodName);
                    foreach (var item in controllerMethods)
                    {
                        var execObjs = item.ToLookup(a => a.MethodInfo.GetParameters().Length).Where(a => a.Count() > 1);
                        foreach (var execObj in execObjs)
                        {
                            Logger.Trace($"RPC方法：{item.Key}[{execObj.Key}]签名冲突,在{string.Join(",", execObj.Select(a => ((IAPIController)a.TypeObject).Name))}");
                        }
                        foreach (var methodInfo in item)
                        {
                            var methodKey = $"{methodInfo.TypeObject?.Name?.ToLower()}.{methodInfo.MethodName}.{methodInfo.MethodInfo.GetParameters().Length}";
                            Actions[methodKey] = methodInfo;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error($"RPC Method Init Error" + ex.Message);
                }
                return Actions;
            }
        }

        private static object ExecutionInvoke(MomRpcInfo ActionInvokeInfo, object objects)
        {
            var Parameters = ActionInvokeInfo.MethodInfo.GetParameters().FirstOrDefault().ParameterType;
            var Parameter = JsonHelper.JsonSerialize(objects);
            var param = JsonHelper.JsonDeserialize(Parameter, Parameters);
            var parameters = new object[] { param };
            var Res = ActionInvokeInfo.Invoke(parameters);
            return Res;
        }
    }

    public class MomRpcInfo
    {
        /// <summary>
        /// 方法名
        /// </summary>
        public string MethodName { get; set; }

        /// <summary>
        /// 类型
        /// </summary>
        public MomApi TypeObject { get; set; }

        /// <summary>
        /// 方法信息
        /// </summary>
        public MethodInfo MethodInfo { get; set; }

        /// <summary>
        /// 参数信息
        /// </summary>
        public string[] Params { get; set; }

        /// <summary>
        /// 参数信息
        /// </summary>
        public string Returns { get; set; }

        /// <summary>
        ///
        /// </summary>
        public FastInvokeHandler Handler { get; set; }

        public object Invoke(object[] args)
        {
            return Handler.Invoke(TypeObject, args);
        }
    }
}